/*
 *  Copyright 2011 yura.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package org.opu.vcforms.transform_t2d.docx;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import org.opu.vcforms.datasource.DataReceiver;
import org.opu.vcforms.datasource.Storage;
import org.opu.vcforms.template.TxtTemplate;
import org.opu.vcforms.transform_t2d.MainProcessor;
import org.opu.vcforms.transform_t2d.Processor;
import org.opu.vcforms.transform_t2d.content.ContentProcessor;
import org.opu.vcforms.template.util.ArchiveUtil;
import org.opu.vcforms.transform_t2d.util.DocxUtil;
import org.opu.vcforms.transform_t2d.util.StringUtil;
import org.xml.sax.SAXException;

/**
 *  Convert docx file to docx file. Docx file represented as a byte array.
 * @author yura
 */
public class Transformer  extends MainProcessor implements Processor<byte[], byte[]>{
    protected final DocxUtil    docxUtil    = new DocxUtil();
    protected final ArchiveUtil archiveUtil = new ArchiveUtil();
    protected final StringUtil  stringUtil  = new StringUtil();

    /**
     *  Create new instance
     * @param receiver needed to send query and get request from database
     * @param userSettings can be empty (user data).
     * @param systemSettings systemSettings system settings (course, semestr, ...).
     *  If it null loads system properties - {@link System#getProperties()}.
     * @param contentProcessor content (can be null)
     */
    public Transformer(DataReceiver receiver, Map<String, Storage> userSettings,
            Properties systemSettings, ContentProcessor contentProcessor) {
        super(receiver, userSettings, systemSettings, contentProcessor);
    }

    /**
     *  Create new instance with nullable content (for main node - document).
     * @param receiver needed to send query and get request from database
     * @param userSettings can be empty (user data).
     * @param systemSettings systemSettings system settings (course, semestr, ...).
     *  If it null loads system properties - {@link System#getProperties()}.
     */
    public Transformer(DataReceiver receiver, Map<String, Storage> userSettings,
            Properties systemSettings) {
        super(receiver, userSettings, systemSettings);
    }

    /**
     * Strategi:
     * 1) Get list of file with content
     * 2) Convert each xml file to txt/template
     * 3) Use transformer for text converter for each file
     * 4) Recriet archive
     */
    @Override
    public byte[] transform(byte[] v) throws UnsupportedOperationException,
            IllegalArgumentException, NoSuchElementException {
        
        // 1
        Map<String, byte[]> archive = toDocxArchive(v);

        Set<String> toParse = docxUtil.documents(archive);
        
        for (String name : toParse) {
            // 2
            byte[] xml;
            try {
                xml = docxUtil.convertOOXMLToDataXML(archive.get(name));
            } catch (SAXException ex) {
                throw new IllegalArgumentException(ex);
            }

            // 3
            final String transformed;
            try {
                transformed = transform(new ByteArrayInputStream(xml));
            } catch (IOException ex) {
                throw new RuntimeException("Can't transform generated dataXml", ex);
            }

            byte[] rmWhiteSpace = stringUtil.rmWhiteSpace(transformed);
            archive.put(name, rmWhiteSpace);
        }

        // 4
        final ByteArrayOutputStream bout = new ByteArrayOutputStream();
        try {
            archiveUtil.writeArchive(archive, bout);
        } catch (IOException ex) {
            throw new IllegalArgumentException(ex);
        }

        return bout.toByteArray();
    }

    /**
     *  Convert byte array to archive, and read all data from it.
     * @param v bate array that represent archive
     * @return
     * @see ArchiveUtil#readArchive(java.io.InputStream)
     * @throws IllegalArgumentException if any error happen at proccess
     */
    protected Map<String, byte[]> toDocxArchive(byte[] v)
            throws IllegalArgumentException {

        try {
            return archiveUtil.readArchive(new ByteArrayInputStream(v));
        } catch (Exception ex) {
            throw new IllegalArgumentException(
                    "Can't represent input data as a archive", ex);
        }
    }

    /**
     * @see TxtTemplate
     * @see TxtTemplate#load(java.io.InputStream) 
     * @see org.opu.vcforms.transform_t2d.text.Transformer
     * @see org.opu.vcforms.transform_t2d.text.Transformer#transform(org.opu.vcforms.template.TxtTemplate)
     */
    protected final String transform(InputStream in) throws IOException {
        TxtTemplate template = new TxtTemplate();
        template.load(in);

        org.opu.vcforms.transform_t2d.text.Transformer instance =
                new org.opu.vcforms.transform_t2d.text.Transformer(
                    dbManager, userSettings, systemSettings, null);

        String result = instance.transform(template);

        return result;
    }

}
